using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Nuwanda.TfsSpotlight.Shell.Exceptions;
using Nuwanda.TfsSpotlight.Shell.Proxies.Interfaces;
using Nuwanda.TfsSpotlight.Shell.Services.Interfaces;

namespace Nuwanda.TfsSpotlight.Shell.Services
{
    public class CommandConfiguration
    {
        public string Command { get; private set; }
        public string Name { get; set; }
        public Image Image { get; set; }
        public Keys Shortcut { get; set; }
        public bool AlwaysActive { get; set; }
        public bool Asynchronous { get; set; }
        private ToolStripMenuItem _toolStripMenuItem;
        public IToolStrip ToolStrip { get; set; }
        public Dictionary<object, Func<bool>> Activators { get; private set; }
        public List<ToolStripItem> SupportingItems { get; private set; }

        private IMenuService MenuService { get; set; }

        public bool IsActive
        {
            get
            {
                if (this.AlwaysActive)
                    return true;

                if (this.Activators.Count == 0)
                    return false;

                foreach (var activator in this.Activators.Values)
                {
                    if (activator() == false)
                        return false;
                }

                return true;
            }
        }

        public CommandConfiguration(IMenuService menuService, string command)
        {
            if(String.IsNullOrEmpty(command))
                throw new MenuConfigurationException("The command cannot be empty.");
            if(menuService == null)
                throw new ArgumentNullException("menuService");

            this.MenuService = menuService;
            this.Command = command;
            this.AlwaysActive = false;
            this.Asynchronous = false;
            this.Activators = new Dictionary<object, Func<bool>>();
            this.SupportingItems = new List<ToolStripItem>();
        }

        /// <summary></summary>
        /// <returns></returns>
        public ToolStripMenuItem ToToolStripItem()
        {
            return this._toolStripMenuItem;
        }

        public void Build()
        {
            this._toolStripMenuItem = new ToolStripMenuItem
                                          {
                                              Text = this.Name,
                                              Image = this.Image,
                                              ToolTipText = this.Name
                                          };
            this._toolStripMenuItem.Click += delegate { this.MenuService.RunCommand(this.Command); };
        }

        public void Invalidate(object key)
        {
            if(this.Activators.ContainsKey(key) == false) return;
            if(this.ToToolStripItem() == null) return;

            EnabeItems(this.AlwaysActive ? true : this.Activators[key]());
        }

        private void EnabeItems(bool enable)
        {
            if(this.ToolStrip == null)
            {
                EnableAux(enable);
            }
            else
            {
                this.ToolStrip.ToolStripInvoker.RunInControlsThread(
                    () => EnableAux(enable));
            }
            
        }

        private void EnableAux(bool enable)
        {
            this.ToToolStripItem().Enabled = enable;

            foreach (var item in this.SupportingItems)
            {
                item.Enabled = enable;
            }
        }

        public void Invalidate()
        {
            if (this.ToToolStripItem() == null) return;

            EnabeItems(IsActive);
        }

        public void Disable(object key)
        {
            if (this.Activators.ContainsKey(key) == false) return;
            if (this.ToToolStripItem() == null) return;

            EnabeItems(this.AlwaysActive); 
        }

        public ToolStripItem ToContextMenuItem()
        {
            var menuItem = new ToolStripMenuItem
                               {
                                   Text = this.Name,
                                   Image = this.Image,
                                   ShowShortcutKeys = false,
                                   ToolTipText = this.Name
                               };
            menuItem.Click += delegate { this.MenuService.RunCommand(this.Command); };

            this.SupportingItems.Add(menuItem);

            return menuItem;
        }
    }
}